﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace GluePathModule
{
    [XmlInclude(typeof(GluePathItemSPLine))]
    public class GluePathItemSPLine : GluePathItemBase
    {
        [Description("SPLine链表"), Category("SPLine设定")]
        public List<PointData> ListPoints
        {
            get;
            set;
        }
        [Description("SPLine链表"), Category("SPLine转换")]
        public List<PointData> ListPointsTransfer
        {
            get;
            set;
        }
        [Browsable(false)]
        public bool bUseZheight
        {
            get;
            set;
        }

        [Browsable(false)]
        public int iDrawStep
        {
            get;
            set;
        }
       
        public GluePathItemSPLine()
        {
            iDrawStep = 0;
            ListPoints = new List<PointData>();
            Name = "";
            Remark = "";
        }

        public override void DrawItem(DrawerControl drawer, DrawMode drawMode = DrawMode.UnitIsSelected)
        {


            if (ListPoints.Count < 2)
                return;
            List<double> listTranXPos = new List<double>();
            List<double> listTranYPos = new List<double>();
            for (int i = 0; i < ListPoints.Count; i++)
            {
                listTranXPos.Add(ListPoints[i].X);
                listTranYPos.Add(ListPoints[i].Y);
            }
            if (drawMode == DrawMode.Background)
            {
                drawer.DrawSPLine(new System.Drawing.Pen(System.Drawing.Color.Gray, 1), listTranXPos, listTranYPos);
                listTranXPos.Clear();
                listTranYPos.Clear();
                return;
            }
            else if (drawMode == DrawMode.UnitIsNotSelect)
            {
                drawer.DrawSPLine(new System.Drawing.Pen(System.Drawing.Color.White, 2), listTranXPos, listTranYPos);
                listTranXPos.Clear();
                listTranYPos.Clear();
                return;
            }
            
                
            if (空动作路径)
                drawer.DrawSPLine(new System.Drawing.Pen(System.Drawing.Color.Blue, 2), listTranXPos, listTranYPos);
            else
                drawer.DrawSPLine(new System.Drawing.Pen(System.Drawing.Color.Green, 2), listTranXPos, listTranYPos);
            if (Select)
            {
                for (int i = 0; i < ListPoints.Count; i++)
                {
                    drawer.DrawPoint(new System.Drawing.Pen(System.Drawing.Color.Red, 2), listTranXPos[i], listTranYPos[i],1);
                }

            }
            listTranXPos.Clear();
            listTranYPos.Clear();



        }
       

       
        public override bool IsOnSelect(double dPosX, double dPosY, double dJudageDis)
        {

           
            bool bSelectTemp = false;
            for (int i = 0; i < ListPoints.Count - 1; i++)
            {
                double Pos1X, Pos1Y, Pos2X, Pos2Y;
                double dMaxX, dMaxY, dMinX, dMinY;
                Pos1X = ListPoints[i].X;
                Pos1Y = ListPoints[i].Y;
                Pos2X = ListPoints[i + 1].X;
                Pos2Y = ListPoints[i + 1].Y;
                dMaxX = Pos1X > Pos2X ? Pos1X : Pos2X;
                dMaxY = Pos1Y > Pos2Y ? Pos1Y : Pos2Y;
                dMinX = Pos1X < Pos2X ? Pos1X : Pos2X;
                dMinY = Pos1Y < Pos2Y ? Pos1Y : Pos2Y;

                if (dPosX > dMinX - 2 && dPosX < dMaxX + 2 && dPosY > dMinY - 2 && dPosY < dMaxY + 2)
                {

                    bSelectTemp = IsOnline(dPosX, dPosY, Pos1X, Pos1Y, Pos2X, Pos2Y, dJudageDis);
                    if (bSelectTemp)
                    {
                        break;
                    }
                }
                else
                {
                    //Select = false;

                }
            }
            if (Select == false)
                Select = bSelectTemp;
            return Select;

        }

       

        private double AngleToHu(double dAngle)
        {
            return dAngle / 180.0 * Math.PI;
        }
        private double HuToAngle(double dHu)
        {
            return dHu / Math.PI * 180.0;
        }
        /// <summary>
        /// 获取两点的距离
        /// 作者：weidy   时间：20200810
        /// </summary>
        /// <returns></returns>
        public double GetDisFrom2Points(double x1, double y1, double x2, double y2)
        {
            return Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
            //return 0.0;
        }


        ///
        ///点x1到线段x1-x2的距离
        /// 作者：陈   时间：20200810
        /// </summary>
        /// <returns></returns>
        public double GetDisFromPointToLine(double dPosX, double dPosY, double dPosX1, double dPosY1, double dPosX2, double dPosY2)
        {
            double space = 0;
            double a, b, c;
            a = GetDisFrom2Points(dPosX1, dPosY1, dPosX2, dPosY2);// lineSpace(x1, y1, x2, y2);// 线段的长度    
            b = GetDisFrom2Points(dPosX1, dPosY1, dPosX, dPosY);// (x1,y1)到点的距离    
            c = GetDisFrom2Points(dPosX2, dPosY2, dPosX, dPosY);// (x2,y2)到点的距离    
            if (c <= 0.000001 || b <= 0.000001)
            {
                space = 0;
                return space;
            }
            if (a <= 0.000001)
            {
                space = b;
                return space;
            }
            if (c * c >= a * a + b * b)
            {
                space = b;
                return space;
            }
            if (b * b >= a * a + c * c)
            {
                space = c;
                return space;
            }
            double p = (a + b + c) / 2;// 半周长    
            double s = Math.Sqrt(p * (p - a) * (p - b) * (p - c));// 海伦公式求面积    
            space = 2 * s / a;// 返回点到线的距离（利用三角形面积公式求高）    
            return space;

        }
        private bool IsOnline(double dPosX, double dPosY, double dPosX1, double dPosY1, double dPosX2, double dPosY2, double dJudageDis)
        {
            double dDistance = GetDisFromPointToLine(dPosX, dPosY, dPosX1, dPosY1, dPosX2, dPosY2);
            return Math.Abs(dDistance) < dJudageDis;
        }
        public override bool GetLastPoint(out double dPosX, out double dPosY, out double dPosZ, out double dPosU)
        {
            
            dPosX = ListPoints[ListPoints.Count - 1].X;
            dPosY = ListPoints[ListPoints.Count - 1].Y;
            dPosZ = ListPoints[ListPoints.Count - 1].Z;
            dPosU = ListPoints[ListPoints.Count - 1].U;
            return false;
        }
        public override bool GetFirstPoint(out double dPosX, out double dPosY, out double dPosZ, out double dPosU)
        {
            
            dPosX = ListPoints[0].X;
            dPosY = ListPoints[0].Y;
           
            dPosZ = ListPoints[0].Z;
            dPosU = ListPoints[0].U;
            return false;
        }
        
        
        
        public override GluePathItemBase CopyItem()
        {
            GluePathItemSPLine itemNew = (GluePathItemSPLine)MemberwiseClone();
            itemNew.ListPoints = new List<PointData>();
            for (int i = 0; i < ListPoints.Count; i++)
            {
                PointData newItem = new PointData(ListPoints[i]);
                itemNew.ListPoints.Add(newItem);
            }

            return itemNew;
        }
        public override void OffSetItem(double dOffSetX, double dOffSetY)
        {
            for (int i = 0; i < ListPoints.Count; i++)
            {
                ListPoints[i].X += dOffSetX;
                ListPoints[i].Y += dOffSetY;
            }
        }
        override public GluePathItemBase Paste()
        {
            //Pos1X = Pos1X + 1;
            //Pos1Y = Pos1Y + 1;
            //Pos2X = Pos2X + 1;
            //Pos2Y = Pos2Y + 1;

            return CopyItem();
        }
        override public void PathUnitMouseDown(double dMouseX, double dMouseY, double dScandle)
        {
            if (Select == false)
                return;
            if (iAdjustStep == 0)
            {
                for (int i = 0; i < ListPoints.Count; i++)
                {
                    if (dMouseX > (ListPoints[i].X - (5 / dScandle)) && dMouseX < (ListPoints[i].X + (5 / dScandle)) && dMouseY > (ListPoints[i].Y - (5 / dScandle)) && dMouseY < (ListPoints[i].Y + (5 / dScandle)))
                    {
                        iAdjustStep = i + 1;
                        break;
                    }

                }


            }
        }
        override public void PathUnitMouseMove(double dMouseX, double dMouseY)
        {
            if (Select == false)
                return;
            if (iAdjustStep > 0)
            {
                ListPoints[iAdjustStep - 1].X = dMouseX;
                ListPoints[iAdjustStep - 1].Y = dMouseY;

            }
        }
        override public void PathUnitMouseUp(double dMouseX, double dMouseY)
        {
            if (Select == false)
                return;
            iAdjustStep = 0;
        }

        public override void OffSetPos(double dOffSetX, double dOffSetY, double dOffSetZ)
        {
            for (int i = 0; i < ListPoints.Count; i++)
            {
                ListPoints[i].X = ListPoints[i].X + dOffSetX;
                ListPoints[i].Y = ListPoints[i].Y + dOffSetY;
                ListPoints[i].Z = ListPoints[i].Z + dOffSetZ;

            }



        }
        public override void SetZPos(double dSetPosZ)
        {
            for (int i = 0; i < ListPoints.Count; i++)
            {
                ListPoints[i].Z = dSetPosZ;
            }

        }
        public override void SetUPos(double dSetPosU)
        {
            for (int i = 0; i < ListPoints.Count; i++)
            {
                ListPoints[i].U = dSetPosU;
            }

        }
        public override void UpdateZheight(double dZHeight)
        {
            for (int i = 0; i < ListPoints.Count; i++)
            {

                  ListPoints[i].Z = dZHeight;
               
            }

        }
        public override void GetItemMinMaxXY(out double dMinX, out double dMinY, out double dMaxX, out double dMaxY)
        {
            //base.GetItemMinMaxXY(out dMinX, out dMinY, out dMaxX, out dMaxY);
            dMinX = 9999;
            dMinY = 9999;
            dMaxX = -9999;
            dMaxY = -9999;

            foreach (PointData linePoint in ListPoints)
            {
                if (linePoint.X < dMinX)
                {
                    dMinX = linePoint.X;
                }
                if (linePoint.Y < dMinY)
                {
                    dMinY = linePoint.Y;
                }
                if (linePoint.X > dMaxX)
                {
                    dMaxX = linePoint.X;
                }
                if (linePoint.Y > dMaxY)
                {
                    dMaxY = linePoint.Y;
                }
            }

        }
        public override void UpdateEndPos(double dNewEndX, double dNewEndY)
        {
            if (ListPoints.Count < 2)
                return;
            ListPoints[ListPoints.Count - 1].X = dNewEndX;
            ListPoints[ListPoints.Count - 1].Y = dNewEndY;
        }
        public override void UpdateStartPos(double dNewStartX, double dNewStartY)
        {
            if (ListPoints.Count < 2)
                return;
            ListPoints[0].X = dNewStartX;
            ListPoints[0].Y = dNewStartY;
        }
        public override void PushItem(List<MotionItemBase> motionItems, GluePathGroup gluePathGroup, GluePathUnit gluePathUnit, int indexId, double dOffsetZ)
        {
            

            SpdData spdXYGlue = new SpdData();
            SpdData spdXYH = new SpdData();
            SpdData spdZH = new SpdData();


            double dFirstPosX, dFirstPosY, dFirstPosZ, dFirstPosU;
            GetFirstPoint(out dFirstPosX, out dFirstPosY, out dFirstPosZ, out dFirstPosU);

            #region 判断胶路类型
            bool bIsFirstItem = false;
            bool bisFinalItem = false;
            bool bContinueWithBeforeItem = false;
            bool bContinueWithAferItem = false;
            bool bIsContinueWithAferAndAfterIsOnGlue = false;
            if (indexId == 0)
            {
                bIsFirstItem = true;
            }
            if (indexId == (gluePathUnit.listContinueItems.Count - 1))
            {
                bisFinalItem = true;
            }
            if (indexId == 0)
            {

            }
            else
            {
                double dBeforeItemPosX, dBeforeItemPosY, dBeforeItemPosZ, dBeforeItemPosU;
                gluePathUnit.listContinueItems[indexId - 1].GetLastPoint(out dBeforeItemPosX, out dBeforeItemPosY,
                    out dBeforeItemPosZ, out dBeforeItemPosU);
                if (Math.Abs(dBeforeItemPosX - dFirstPosX) < 0.5 && Math.Abs(dBeforeItemPosY - dFirstPosY) < 0.5 && Math.Abs(dBeforeItemPosZ - dFirstPosZ) < 0.5)
                {
                    bContinueWithBeforeItem = true;
                }
            }
            if (indexId == (gluePathUnit.listContinueItems.Count - 1))
            {
                bContinueWithAferItem = false;
            }
            else
            {
                double dNextItemPosX, dNextItemPosY, dNextItemPosZ, dNextItemPosU;
                double dCurrentEndPosX, dCurrentEndPosY, dCurrentEndPosZ, dCurrentEndPosU;
                GetLastPoint(out dCurrentEndPosX, out dCurrentEndPosY, out dCurrentEndPosZ, out dCurrentEndPosU);
                gluePathUnit.listContinueItems[indexId + 1].GetFirstPoint(out dNextItemPosX, out dNextItemPosY,
                    out dNextItemPosZ, out dNextItemPosU);
                if (Math.Abs(dCurrentEndPosX - dNextItemPosX) < 0.5 && Math.Abs(dCurrentEndPosY - dNextItemPosY) < 0.5 && Math.Abs(dCurrentEndPosZ - dNextItemPosZ) < 0.5)
                {
                    bContinueWithAferItem = true;
                    if (gluePathUnit.listContinueItems[indexId + 1].空动作路径 == false && gluePathUnit.listContinueItems[indexId + 1].Disable == false)
                    {
                        bIsContinueWithAferAndAfterIsOnGlue = true;
                    }
                }
            }
            #endregion

            #region 速度设定

            if (使用单独涂胶速度)
            {
                spdXYGlue.dMoveSpd = 单独涂胶速度;
            }
            else
            {
                if (空动作路径)
                {
                    spdXYGlue.dMoveSpd = gluePathUnit.全局XY高速速度;
                }
                else
                {
                    spdXYGlue.dMoveSpd = gluePathUnit.全局涂胶速度;
                }
            }
            spdXYH.dStartSpd = gluePathUnit.全局开始速度;
            spdXYH.dMoveSpd = gluePathUnit.全局XY高速速度;
            spdXYH.dEndSpd = gluePathUnit.全局结束速度;
            spdXYH.dAcc = gluePathUnit.全局加速度;
            spdXYH.dDec = gluePathUnit.全局减速度;
            spdZH.dStartSpd = gluePathUnit.全局开始速度;
            spdZH.dMoveSpd = gluePathUnit.全局Z高速速度;
            spdZH.dEndSpd = gluePathUnit.全局结束速度;
            spdZH.dAcc = gluePathUnit.全局加速度;
            spdZH.dDec = gluePathUnit.全局减速度;
            if (bIsFirstItem && bisFinalItem)//只有一个点
            {
                spdXYGlue.dStartSpd = gluePathUnit.全局开始速度;
                spdXYGlue.dEndSpd = gluePathUnit.全局结束速度;
                spdXYGlue.dAcc = gluePathUnit.全局加速度;
                spdXYGlue.dDec = gluePathUnit.全局减速度;
            }
            if (bIsFirstItem && (!bContinueWithBeforeItem) && (bContinueWithAferItem) && (!bisFinalItem))//流程的第一个点和后面有连接
            {

                spdXYGlue.dStartSpd = gluePathUnit.全局开始速度;
                spdXYGlue.dEndSpd = spdXYGlue.dMoveSpd;
                spdXYGlue.dAcc = gluePathUnit.全局加速度;
                spdXYGlue.dDec = gluePathUnit.全局减速度;

            }
            if (!bIsFirstItem && (!bContinueWithBeforeItem) && (bContinueWithAferItem) && (!bisFinalItem))//流程中间点，没有和前面的连接，与后面的连接
            {

                spdXYGlue.dStartSpd = gluePathUnit.全局开始速度;
                spdXYGlue.dEndSpd = spdXYGlue.dMoveSpd;
                spdXYGlue.dAcc = gluePathUnit.全局加速度;
                spdXYGlue.dDec = gluePathUnit.全局减速度;

            }
            if (!bIsFirstItem && (bContinueWithBeforeItem) && (bContinueWithAferItem) && (!bisFinalItem))//流程中间点，和前面的连接，与后面的连接
            {

                spdXYGlue.dStartSpd = spdXYGlue.dMoveSpd;
                spdXYGlue.dEndSpd = spdXYGlue.dMoveSpd;
                spdXYGlue.dAcc = gluePathUnit.全局加速度;
                spdXYGlue.dDec = gluePathUnit.全局减速度;
            }
            if (!bIsFirstItem && (bContinueWithBeforeItem) && (!bContinueWithAferItem) && (!bisFinalItem))//流程中间点，和前面的连接，没有与后面的连接
            {
                spdXYGlue.dStartSpd = spdXYGlue.dMoveSpd;
                spdXYGlue.dEndSpd = gluePathUnit.全局结束速度;
                spdXYGlue.dAcc = gluePathUnit.全局加速度;
                spdXYGlue.dDec = gluePathUnit.全局减速度;

            }
            if (!bIsFirstItem && (!bContinueWithBeforeItem) && (!bContinueWithAferItem) && (!bisFinalItem))//流程中间点，没有和前面的连接，没有与后面的连接
            {
                spdXYGlue.dStartSpd = gluePathUnit.全局开始速度;
                spdXYGlue.dEndSpd = gluePathUnit.全局结束速度;
                spdXYGlue.dAcc = gluePathUnit.全局加速度;
                spdXYGlue.dDec = gluePathUnit.全局减速度;
            }
            if (!bIsFirstItem && (bContinueWithBeforeItem) && (!bContinueWithAferItem) && (bisFinalItem))//流程最后一个线段，和前面连接
            {
                spdXYGlue.dStartSpd = spdXYGlue.dMoveSpd;
                spdXYGlue.dEndSpd = gluePathUnit.全局结束速度;
                spdXYGlue.dAcc = gluePathUnit.全局加速度;
                spdXYGlue.dDec = gluePathUnit.全局减速度;
            }
            if (!bIsFirstItem && (!bContinueWithBeforeItem) && (!bContinueWithAferItem) && (bisFinalItem))//流程最后一个线段，没有和前面连接
            {
                spdXYGlue.dStartSpd = gluePathUnit.全局开始速度;
                spdXYGlue.dEndSpd = gluePathUnit.全局结束速度;
                spdXYGlue.dAcc = gluePathUnit.全局加速度;
                spdXYGlue.dDec = gluePathUnit.全局减速度;
            }
            #endregion

            TranferPosToCur(gluePathUnit,bContinueWithBeforeItem, motionItems,dOffsetZ);

            #region 轨迹设定


            if (bContinueWithBeforeItem == false)
            {
                MotionItemLine motionItemLineUp = new MotionItemLine(spdXYH, ListPointsTransfer[0]);
                motionItemLineUp.Point.Z = gluePathUnit.全局安全高度Z;
                motionItems.Add(motionItemLineUp);
                MotionItemLine motionItemLineStart = new MotionItemLine(spdZH, ListPointsTransfer[0]);
                motionItems.Add(motionItemLineStart);

            }

            if (空动作路径 == false)
            {
                MotionItemOutput motionItemOutput = new MotionItemOutput();
                motionItemOutput.On = true;
                motionItems.Add(motionItemOutput);
            }

            if (this.开胶后延时时间 > 0)
            {
                MotionItemDelay motionItemDelay = new MotionItemDelay();
                motionItemDelay.dDelayTime = this.开胶后延时时间;
                motionItems.Add(motionItemDelay);
            }


            for (int i = 1; i < ListPoints.Count; i++)
            {
                MotionItemLine motionItemLine = new MotionItemLine(spdXYGlue, ListPointsTransfer[i]);
                motionItems.Add(motionItemLine);
            }

            if (bIsContinueWithAferAndAfterIsOnGlue == false)
            {
                MotionItemOutput motionItemOutput = new MotionItemOutput();
                motionItemOutput.On = false;
                motionItems.Add(motionItemOutput);
            }
            if (bContinueWithAferItem == false)
            {
                MotionItemLine motionItemLineUp = new MotionItemLine(spdZH, ListPointsTransfer[ListPoints.Count-1]);
                motionItemLineUp.Point.Z = gluePathUnit.全局安全高度Z;
                motionItems.Add(motionItemLineUp);
            }
            #endregion
        }

        private void TranferPosToCur(GluePathUnit gluePathUnit, bool bContinueWithBeforeItem, List<MotionItemBase> motionItems,double dOffsetZ)
        {
            ListPointsTransfer = new List<PointData>();
           
            for (int i = 0; i < ListPoints.Count; i++)
            {
                if (bContinueWithBeforeItem)
                {
                    ListPoints[i].U = motionItems[motionItems.Count - 1].dEndU;
                }
                PointData pointDataLocalPos = WhereAtLocal(ListPoints[i], gluePathUnit.StandardLocalX, gluePathUnit.StandardLocalY, gluePathUnit.StandardLocalU);
                PointData PosTransfer = TranLocalToMotor(pointDataLocalPos, gluePathUnit.CurrentLocalX, gluePathUnit.CurrentLocalY, gluePathUnit.CurrentLocalU);
                AddToolOffSet(gluePathUnit, PosTransfer);
                PosTransfer.Z = PosTransfer.Z -dOffsetZ;
                ListPointsTransfer.Add(PosTransfer);
            }   
        }
    }
}
